package com.sharp.portal.service;

import com.github.pagehelper.PageInfo;
import com.sharp.framework.service.cache.FrameCacheService;
import com.sharp.kernel.constant.db.SqlConstant;
import com.sharp.kernel.mybatis.dao.entity.Columns;
import com.sharp.kernel.mybatis.dao.repository.ColumnsService;
import com.sharp.kernel.mybatis.repository.BaseMysqlRepository;
import com.sharp.kernel.utils.DbUtil;
import com.sharp.kernel.utils.JsonUtil;
import com.sharp.kernel.utils.ReflectionUtil;
import com.sharp.kernel.utils.StringUtil;
import com.sharp.kernel.vo.query.QueryReqVO;
import com.sharp.portal.constant.anno.PortalPage;
import com.sharp.portal.dao.entity.CoPortal;
import com.sharp.portal.dao.entity.CoPortalCondition;
import com.sharp.portal.dao.entity.CoPortalLayout;
import com.sharp.portal.dao.repository.CoPortalConditionService;
import com.sharp.portal.dao.repository.CoPortalLayoutService;
import com.sharp.portal.dao.repository.CoPortalService;
import com.sharp.portal.utils.PortalUtil;
import com.sharp.portal.vo.ConditionVO;
import com.sharp.portal.vo.FieldDisplayVO;
import com.sharp.portal.vo.ModelDisplayVO;
import com.sharp.portal.vo.QueryConditionReq;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.*;

/**
 * Title: PortalQueryService
 * Description: Copyright: Copyright (c) 2019 Company: BHFAE
 *
 * @author Sharp
 * @date 2020/11/13 21:57
 */

@Slf4j
@Service
public class PortalQueryService {

    @Resource
    private CoPortalService coPortalService;
    @Resource
    private CoPortalConditionService coPortalConditionService;
    @Resource
    private FrameCacheService frameCacheService;


    @SuppressWarnings({"rawtypes", "unchecked"})
    public <ENTITY, SERVICE extends BaseMysqlRepository> PageInfo<ENTITY> query(QueryConditionReq req, SERVICE service,
                                                                                Class<ENTITY> entityClazz,
                                                                                PageInfo<?> pageInfo) {
        Example example = PortalUtil.buildExampleByQueryConditionReq(req, service, entityClazz);
        return service.select(example, pageInfo);
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    public <ENTITY, SERVICE extends BaseMysqlRepository> List<ENTITY> query(QueryConditionReq req, SERVICE service,
                                                                            Class<ENTITY> entityClazz) {
        Example example = PortalUtil.buildExampleByQueryConditionReq(req, service, entityClazz);
        return service.select(example);
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    public <ENTITY, SERVICE extends BaseMysqlRepository> PageInfo<ENTITY> queryAll(QueryReqVO req, SERVICE service,
                                                                                   Class<ENTITY> entityClazz) {
        Example example = service.getExample();
        Example.Criteria criteria = example.createCriteria();
        if (ReflectionUtil.existedField(entityClazz, SqlConstant.UPDATE_FIELD)) {
            if (req.getQueryStartAt() != null) {
                criteria.andGreaterThanOrEqualTo(SqlConstant.UPDATE_FIELD, req.getQueryStartAt());
            }
            if (req.getQueryEndAt() != null) {
                criteria.andLessThanOrEqualTo(SqlConstant.UPDATE_FIELD, req.getQueryEndAt());
            }
        }
        PageInfo<ENTITY> pageInfo = DbUtil.buildPageInfo(req, entityClazz);
        return service.select(example, pageInfo);
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    public <ENTITY, SERVICE extends BaseMysqlRepository> PageInfo<ENTITY> getAllValid(SERVICE service,
                                                                                      Class<ENTITY> entityClazz,
                                                                                      PageInfo<ENTITY> pageInfo) {
        PageInfo<ENTITY> res;
        if (ReflectionUtil.existedField(entityClazz, SqlConstant.VALID_FIELD)) {
            res = service.selectValid(pageInfo);
        } else {
            res = service.select(pageInfo);
        }
        return res;
    }

    public List<ConditionVO> getCondition(String path) {
        List<CoPortalCondition> coPortalConditionList = coPortalConditionService.getCondition(path);
        return ReflectionUtil.copyList(coPortalConditionList, ConditionVO.class);
    }

    public List<LinkedHashMap<String, String>> dataDisplayConvert(List<?> dataList,
                                                                  Map<String, FieldDisplayVO> fieldMap) {
        List<LinkedHashMap<String, String>> resList = new ArrayList<>();
        Map<String, FieldDisplayVO> dictMap = new HashMap<>(fieldMap.size());
        fieldMap.forEach((property, field) -> {
            if (StringUtils.isNotBlank(field.getReference())) {
                dictMap.put(property, field);
            }
        });
        for (Object obj : dataList) {
            LinkedHashMap<String, String> res = new LinkedHashMap<>();
            Map<String, String> map = JsonUtil.readJson(obj, Map.class, String.class, String.class);
            map.forEach((property, value) -> {
                if (StringUtil.convertSwitch(fieldMap.get(property).getHidden())) {
                    if (dictMap.get(property) != null) {
                        String display = frameCacheService.getDictLabelByValue(dictMap.get(property).getReference(),
                                value);
                        res.put(property, display);
                    } else {
                        res.put(property, value);
                    }
                }
            });
            resList.add(res);
        }
        return resList;
    }

    public void convertLinkedHashMapDict(List<LinkedHashMap<String, String>> dataList, Map<String, FieldDisplayVO> fieldMap) {
        Map<String, FieldDisplayVO> dictMap = new HashMap<>(fieldMap.size());
        fieldMap.forEach((property, field) -> {
            if (StringUtils.isNotBlank(field.getReference())) {
                dictMap.put(property, field);
            }
        });
        for (LinkedHashMap<String, String> obj : dataList) {
            dictMap.forEach((property, fieldDisplayVO) -> {
                String label = obj.get(property);
                String value = frameCacheService.getDictValueByLabel(fieldDisplayVO.getReference(), label);
                obj.put(property, value);
            });
        }
    }
}
